home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #9 / Amiga Plus CD - 2004 - No. 09.iso / amigaplus / games / wormwars / source / le.c < prev    next >
C/C++ Source or Header  |  2004-08-03  |  37KB  |  1,021 lines

  1. // 1. INCLUDES -----------------------------------------------------------
  2.  
  3. #include <exec/types.h>
  4. #include <exec/memory.h>
  5. #include <exec/alerts.h>
  6.  
  7. #include "diff.h"
  8. #include "same.h"
  9. #include "amiga.h"
  10.  
  11. #include <intuition/intuition.h> // for struct Window, etc.
  12. #include <libraries/gadtools.h>  // for GT_VisualInfo, etc.
  13.  
  14. #include <clib/exec_protos.h>
  15. #include <clib/graphics_protos.h>
  16. #include <clib/intuition_protos.h>
  17. #include <clib/gadtools_protos.h>
  18.  
  19. #include <stdlib.h>              // for EXIT_SUCCESS, etc.
  20.  
  21. // 2. DEFINES ------------------------------------------------------------
  22.  
  23. #define ALTJUMP         5
  24.  
  25. /* pseudo-gadgets */
  26. #define PSEUDOGADGETS   8    // counting from 1
  27. #define GADGETX         (-2) // negatives must be within parentheses
  28. #define EMPTYGADGET    ((fieldy / 2) - 7)
  29. #define SILVERGADGET   ((fieldy / 2) - 5)
  30. #define GOLDGADGET     ((fieldy / 2) - 3)
  31. #define DYNAMITEGADGET ((fieldy / 2) - 1)
  32. #define WOODGADGET     ((fieldy / 2) + 1)
  33. #define STONEGADGET    ((fieldy / 2) + 3)
  34. #define METALGADGET    ((fieldy / 2) + 5)
  35. #define FROSTGADGET    ((fieldy / 2) + 7)
  36.  
  37. // 3. EXPORTED VARIABLES -------------------------------------------------
  38.  
  39. // 4. IMPORTED VARIABLES -------------------------------------------------
  40.  
  41. IMPORT struct Window*        MainWindowPtr;
  42. IMPORT struct Menu*          MenuPtr;
  43. IMPORT struct VisualInfo*    VisualInfoPtr;
  44. IMPORT struct timerequest*   TimerRqPtr;
  45. IMPORT struct InputEvent     GameEvent;
  46. IMPORT struct Screen*        ScreenPtr;
  47.  
  48. IMPORT ABOOL               anims,
  49.                            clearthem,
  50.                            icons,
  51.                            modified,
  52.                            titlebar;
  53. IMPORT SBYTE               a,
  54.                            board[MAXLEVELS + 1][MINFIELDX + 1][MINFIELDY + 1],
  55.                            startx[MAXLEVELS + 1],
  56.                            starty[MAXLEVELS + 1],
  57.                            level, levels;
  58. IMPORT SWORD               fieldx, fieldy;
  59.  
  60. // 5. MODULE VARIABLES ---------------------------------------------------
  61.  
  62. MODULE ABOOL               sticky = FALSE;
  63. MODULE UBYTE               brush  = STONE;
  64. MODULE SBYTE               fex    = MINFIELDX / 2,
  65.                            fey    = MINFIELDY / 2;
  66.  
  67. MODULE UWORD chip CustomPointer[] =
  68. {   0x0000, 0x0000, /* reserved */
  69.  
  70.     0xF800, 0xFC00, /* 1st row 1st plane, 1st row 2nd plane */
  71.     0xF800, 0x8400, /* 2nd row 1st plane, 2nd row 2nd plane */
  72.     0xF800, 0x8400, /* 3rd row 1st plane, 3rd row 2nd plane */
  73.     0xF800, 0x8400, /* 4th row 1st plane, 4th row 2nd plane */
  74.     0xF800, 0x8400, /* 5th row 1st plane, 5th row 2nd plane */
  75.     0x8000, 0xFC00, /* 6th row 1st plane, 6th row 2nd plane */
  76.  
  77.     0x0000, 0x0000  /* reserved */
  78.  
  79. /*  11111000-------- 11111100--------
  80.     11111000-------- 10000100--------
  81.     11111000-------- 10000100--------
  82.     11111000-------- 10000100--------
  83.     11111000-------- 10000100--------
  84.     10000000-------- 11111100-------- */
  85.  
  86. };
  87.  
  88. // 6. MODULE STRUCTURES --------------------------------------------------
  89.  
  90. // 7. MODULE FUNCTIONS ---------------------------------------------------
  91.  
  92. MODULE void setpointer(UBYTE brush);
  93. MODULE void undot(void);
  94. MODULE void stamp(UBYTE square);
  95. MODULE void fillfield(UBYTE which);
  96. MODULE void underline(UBYTE square);
  97. MODULE SBYTE oldxpixeltosquare(SWORD x);
  98. MODULE SBYTE oldypixeltosquare(SWORD y);
  99. MODULE SBYTE xpixeltosquare(SWORD x);
  100. MODULE SBYTE ypixeltosquare(SWORD y);
  101. MODULE void levelappend(void);
  102. MODULE void leveldelete(void);
  103. MODULE void levelerase(void);
  104. MODULE void levelinsert(void);
  105. MODULE void copyfield(UBYTE source, UBYTE destination);
  106. MODULE SBYTE fexwrap(SBYTE x);
  107. MODULE SBYTE feywrap(SBYTE y);
  108.  
  109. // 8. CODE ---------------------------------------------------------------
  110.  
  111. AGLOBAL void fieldedit(void)
  112. {   AUTO    ABOOL                leftdown  = FALSE,
  113.                                  timer     = FALSE;
  114.     AUTO    SBYTE                pointerx, pointery,
  115.                                  which,
  116.                                  x, y;
  117.     AUTO    SWORD                mousex, mousey;
  118.     AUTO    UWORD                code, qual;
  119.     AUTO    ULONG                class;
  120.     AUTO    struct IntuiMessage* MsgPtr;
  121.     AUTO    struct MenuItem*     ItemPtr;
  122.     PERSIST ABOOL                clipboarded = FALSE;
  123.     PERSIST UBYTE                clipboard[MINFIELDX + 1][MINFIELDY + 1];
  124.  
  125.     say("Level Editor", WHITE);
  126.     setpointer(brush);
  127.     if (level > levels)
  128.         level = levels;
  129.     OnMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, NOITEM, NOSUB));
  130.     if (!clipboarded)
  131.         OffMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, IN_PASTE, NOSUB));
  132.  
  133.     /* draw pseudo-gadgets */
  134.     
  135.     clearscreen();
  136.     for (which = 0; which < PSEUDOGADGETS; which++)
  137.     {   DrawBevelBox
  138.         (   MainWindowPtr->RPort,
  139.             STARTXPIXEL - (SQUAREX * 2) - 4,
  140.             FIELDCENTREY - (SQUAREY * (PSEUDOGADGETS - 1)) + (which * 2 * SQUAREY) - 4,
  141.             SQUAREX + 8,
  142.             SQUAREY + 8,
  143.             GT_VisualInfo, VisualInfoPtr,
  144.             TAG_DONE
  145.         );
  146.     }
  147.     SetAPen(MainWindowPtr->RPort, WHITE);
  148.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (   EMPTYGADGET * SQUAREY));
  149.     Text(MainWindowPtr->RPort, "F1:", 3);
  150.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (  SILVERGADGET * SQUAREY));
  151.     Text(MainWindowPtr->RPort, "F2:", 3);
  152.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (    GOLDGADGET * SQUAREY));
  153.     Text(MainWindowPtr->RPort, "F3:", 3);
  154.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (DYNAMITEGADGET * SQUAREY));
  155.     Text(MainWindowPtr->RPort, "F4:", 3);
  156.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (    WOODGADGET * SQUAREY));
  157.     Text(MainWindowPtr->RPort, "F5:", 3);
  158.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (   STONEGADGET * SQUAREY));
  159.     Text(MainWindowPtr->RPort, "F6:", 3);
  160.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (   METALGADGET * SQUAREY));
  161.     Text(MainWindowPtr->RPort, "F7:", 3);
  162.     Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 10 + (   FROSTGADGET * SQUAREY));
  163.     Text(MainWindowPtr->RPort, "F8:", 3);
  164.  
  165.     draw(GADGETX,    EMPTYGADGET,    EMPTY);
  166.     draw(GADGETX,   SILVERGADGET,   SILVER);
  167.     draw(GADGETX,     GOLDGADGET,     GOLD);
  168.     draw(GADGETX, DYNAMITEGADGET, DYNAMITE);
  169.     draw(GADGETX,     WOODGADGET,     WOOD);
  170.     draw(GADGETX,    STONEGADGET,    STONE);
  171.     draw(GADGETX,    METALGADGET,    METAL);
  172.     draw(GADGETX,    FROSTGADGET,    FROST);
  173.  
  174.     underline(brush);
  175.     turborender();
  176.     saylevel(WHITE);
  177.     clearkybd();
  178.  
  179.     if (!valid(fex, fey))
  180.     {   fex = startx[level];
  181.         fey = starty[level];
  182.     }
  183.     dot();
  184.  
  185.     if (!(ModifyIDCMP(MainWindowPtr, IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS | IDCMP_CLOSEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MENUPICK | IDCMP_MENUVERIFY | IDCMP_REFRESHWINDOW | IDCMP_MOUSEMOVE)))
  186.     {   DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: ModifyIDCMP() failed!\0", 24);
  187.     cleanexit(EXIT_FAILURE);
  188.     }
  189.     while (a == FIELDEDIT)
  190.     {   Wait(1L << MainWindowPtr->UserPort->mp_SigBit);
  191.         while (MsgPtr = GT_GetIMsg(MainWindowPtr->UserPort))
  192.         {   class  = MsgPtr->Class;
  193.             code   = MsgPtr->Code;
  194.             qual   = MsgPtr->Qualifier;
  195.             mousex = MsgPtr->MouseX;
  196.             mousey = MsgPtr->MouseY;
  197.             if (class == IDCMP_MENUVERIFY && code == MENUHOT)
  198.             {   if
  199.                 (   mousex >= STARTXPIXEL
  200.                  && mousex <=   ENDXPIXEL
  201.                  && mousey >= STARTYPIXEL
  202.                  && mousey <=   ENDYPIXEL
  203.                  && !(qual & IEQUALIFIER_RCOMMAND)
  204.                 )
  205.                 {   MsgPtr->Code = MENUCANCEL;
  206.             }   }
  207.             GT_ReplyIMsg(MsgPtr);
  208.             switch (class)
  209.             {
  210.             case IDCMP_MOUSEMOVE:
  211.                 if (leftdown)
  212.                 {   pointerx = xpixeltosquare(mousex);
  213.                     pointery = ypixeltosquare(mousey);
  214.                     if
  215.                     (   (pointerx != fex || pointery != fey)
  216.                      && valid(pointerx, pointery)
  217.                     )
  218.                     {   undot();
  219.                         fex = pointerx;
  220.                         fey = pointery;
  221.                         stamp(brush);
  222.                 }   }
  223.             break;
  224.             case IDCMP_MENUPICK:
  225.                 while (code != MENUNULL)
  226.                 {   ItemPtr = ItemAddress(MenuPtr, code);
  227.                     switch (MENUNUM(code))
  228.                     {
  229.                     case MN_PROJECT:
  230.                         switch (ITEMNUM(code))
  231.                         {
  232.                         case IN_NEW:
  233.                             newfields();
  234.                             say("New done.", WHITE);
  235.                         break;
  236.                         case IN_OPEN:
  237.                             fileopen(FALSE);
  238.                         break;
  239.                         case IN_REVERT:
  240.                             fileopen(TRUE);
  241.                         break;
  242.                         case IN_SAVE:
  243.                             if (modified)
  244.                             {   clearhiscores();
  245.                                 modified = FALSE;
  246.                             }
  247.                             filesaveas(FALSE);
  248.                             turborender();
  249.                         break;
  250.                         case IN_SAVEAS:
  251.                             if (modified)
  252.                             {   clearhiscores();
  253.                                 modified = FALSE;
  254.                             }
  255.                             filesaveas(TRUE);
  256.                             turborender();
  257.                         break;
  258.                         case IN_PROJECTDELETE:
  259.                             filedelete();
  260.                         break;
  261.                         case IN_QUIT:
  262.                             if (verify())
  263.                                 cleanexit(EXIT_SUCCESS);
  264.                         break;
  265.                         default:
  266.                         break;
  267.                         }
  268.                     break;
  269.                     case MN_EDIT:
  270.                         switch (ITEMNUM(code))
  271.                         {
  272.                         case IN_CUT:
  273.                             for (x = 0; x <= MINFIELDX; x++)
  274.                                 for (y = 0; y <= MINFIELDY; y++)
  275.                                     clipboard[x][y] = board[level][x][y];
  276.                             leveldelete();
  277.                             clipboarded = TRUE;
  278.                             modified = TRUE;
  279.                             OnMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, IN_PASTE, NOSUB));
  280.                         break;
  281.                         case IN_COPY:
  282.                             for (x = 0; x <= MINFIELDX; x++)
  283.                                 for (y = 0; y <= MINFIELDY; y++)
  284.                                     clipboard[x][y] = board[level][x][y];
  285.                             clipboarded = TRUE;
  286.                             OnMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, IN_PASTE, NOSUB));
  287.                         break;
  288.                         case IN_PASTE:
  289.                             for (x = 0; x <= MINFIELDX; x++)
  290.                                 for (y = 0; y <= MINFIELDY; y++)
  291.                                     board[level][x][y] = clipboard[x][y];
  292.                             turborender();
  293.                             modified = TRUE;
  294.                         break;
  295.                         case IN_ERASE:
  296.                             levelerase();
  297.                         break;
  298.                         case IN_INSERT:
  299.                             levelinsert();
  300.                         break;
  301.                         case IN_EDITDELETE:
  302.                             leveldelete();
  303.                         break;
  304.                         case IN_APPEND:
  305.                             levelappend();
  306.                         break;
  307.                         default:
  308.                         break;
  309.                         }
  310.                     break;
  311.                     case MN_SETTINGS:
  312.                         switch(ITEMNUM(code))
  313.                         {
  314.                         case IN_ANIMATIONS:
  315.                             if (ItemPtr->Flags & CHECKED)
  316.                             {   anims = TRUE;
  317.                             } else
  318.                             {   anims = FALSE;
  319.                             }
  320.                         break;
  321.                         case IN_CREATEICONS:
  322.                             if (ItemPtr->Flags & CHECKED)
  323.                             {   icons = TRUE;
  324.                             } else
  325.                             {   icons = FALSE;
  326.                             }
  327.                         break;
  328.                         case IN_SHOWTITLEBAR:
  329.                             if (ItemPtr->Flags & CHECKED)
  330.                             {   titlebar = TRUE;
  331.                             } else
  332.                             {   titlebar = FALSE;
  333.                             }
  334.                             ShowTitle(ScreenPtr, titlebar);
  335.                         break;
  336.                         default:
  337.                         break;
  338.                         }
  339.                     break;
  340.                     case MN_HELP:
  341.                         switch(ITEMNUM(code))
  342.                         {
  343.                         case IN_CREATURES:
  344.                             help(ORB);
  345.                         break;
  346.                         case IN_OBJECTS:
  347.                             help(AFFIXER);
  348.                         break;
  349.                         case IN_ABOUT:
  350.                             helpabout();
  351.                         break;
  352.                         default:
  353.                         break;
  354.                         }
  355.                     break;
  356.                     default:
  357.                     break;
  358.                     } // hctiws
  359.                     code = ItemPtr->NextSelect;
  360.                 } // elihw
  361.             break;
  362.             case IDCMP_RAWKEY:
  363.                 if (!(qual & IEQUALIFIER_REPEAT))
  364.                 {   effect(FXCLICK);
  365.                 }
  366.                 switch(code)
  367.                 {
  368.                 case DELETE:
  369.                     if (!(qual & IEQUALIFIER_REPEAT))
  370.                     {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  371.                             level = 1;
  372.                         elif (--level < 0)
  373.                             level = levels;
  374.                         saylevel(WHITE);
  375.                         turborender();
  376.                     }
  377.                 break;
  378.                 case HELP:
  379.                     if (!(qual & IEQUALIFIER_REPEAT))
  380.                     {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  381.                             level = levels;
  382.                         elif (++level > levels)
  383.                             level = 0;
  384.                         saylevel(WHITE);
  385.                         turborender();
  386.                     }
  387.                 break;
  388.                 case M:
  389.                     if (!(qual & IEQUALIFIER_REPEAT))
  390.                         toggle(M);
  391.                 break;
  392.                 case F:
  393.                     if (!(qual & IEQUALIFIER_REPEAT))
  394.                         toggle(F);
  395.                 break;
  396.                 case ESCAPE:
  397.                     if (!(qual & IEQUALIFIER_REPEAT))
  398.                     {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  399.                         {   if (verify())
  400.                             {   cleanexit(EXIT_SUCCESS);
  401.                         }   }
  402.                         else
  403.                         {   a = GAMEOVER;
  404.                     }   }
  405.                 break;
  406.                 case SPACEBAR:
  407.                 case RETURN:
  408.                 case ENTER:
  409.                     if (!(qual & IEQUALIFIER_REPEAT))
  410.                         a = GAMEOVER;
  411.                 break;
  412.                 case NUMERICOPEN:
  413.                 case COMMA:
  414.                     setpointer(NORMAL);
  415.                     underline(255);
  416.  
  417.                     if (brush > 0)
  418.                     {   brush--;
  419.                     } else
  420.                     {   brush = LASTOBJECT; // note sign issues
  421.                     }
  422.                     stamp(brush);
  423.                 break;
  424.                 case NUMERICCLOSE:
  425.                 case ALPHADOT:
  426.                     setpointer(NORMAL);
  427.                     underline(255);
  428.  
  429.                     if (brush < LASTOBJECT)
  430.                     {   brush++;
  431.                     } else
  432.                     {   brush = 0;
  433.                     }
  434.                     stamp(brush);
  435.                 break;
  436.                 case C:
  437.                     effect(FXUSE_TELEPORT); /* interesting */
  438.                     undot();
  439.                     fex = MINFIELDX / 2;
  440.                     fey = MINFIELDY / 2;
  441.                     dot();
  442.                 break;
  443.                 case S:
  444.                     stamp(START);
  445.                 break;
  446.                 case KEY_U:
  447.                     stamp(ARROWUP);
  448.                 break;
  449.                 case D:
  450.                     stamp(ARROWDOWN);
  451.                 break;
  452.                 case ALPHAONE:
  453.                     stamp(EMPTY);
  454.                 break;
  455.                 case ALPHATWO:
  456.                     stamp(SILVER);
  457.                 break;
  458.                 case ALPHATHREE:
  459.                     stamp(GOLD);
  460.                 break;
  461.                 case ALPHAFOUR:
  462.                     stamp(DYNAMITE);
  463.                 break;
  464.                 case ALPHAFIVE:
  465.                     stamp(WOOD);
  466.                 break;
  467.                 case ALPHASIX:
  468.                     stamp(STONE);
  469.                 break;
  470.                 case ALPHASEVEN:
  471.                     stamp(METAL);
  472.                 break;
  473.                 case ALPHAEIGHT:
  474.                     stamp(FROST);
  475.                 break;
  476.                 case F1:
  477.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  478.                     {   fillfield(EMPTY);
  479.                     } else setbrush(EMPTY);
  480.                 break;
  481.                 case F2:
  482.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  483.                     {   fillfield(SILVER);
  484.                     } else setbrush(SILVER);
  485.                 break;
  486.                 case F3:
  487.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  488.                     {   fillfield(GOLD);
  489.                     } else setbrush(GOLD);
  490.                 break;
  491.                 case F4:
  492.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  493.                     {   fillfield(DYNAMITE);
  494.                     } else setbrush(DYNAMITE);
  495.                 break;
  496.                 case F5:
  497.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  498.                     {   fillfield(WOOD);
  499.                     } else setbrush(WOOD);
  500.                 break;
  501.                 case F6:
  502.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  503.                     {   fillfield(STONE);
  504.                     } else setbrush(STONE);
  505.                 break;
  506.                 case F7:
  507.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  508.                     {   fillfield(METAL);
  509.                     } else setbrush(METAL);
  510.                 break;
  511.                 case F8:
  512.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  513.                     {   fillfield(FROST);
  514.                     } else setbrush(FROST);
  515.                 break;
  516.                 case NUMERICZERO:
  517.                     if (!(qual & IEQUALIFIER_REPEAT))
  518.                     {   if (!sticky)
  519.                         {   sticky = TRUE;
  520.                             say("Sticky mode on", WHITE);
  521.                             stamp(brush);
  522.                         } else
  523.                         {   sticky = FALSE;
  524.                             say("Sticky mode off", WHITE);
  525.                             dot();
  526.                     }   }
  527.                 break;
  528.                 case NUMERICDOT:
  529.                     stamp(brush);
  530.                 break;
  531.                 case KEY_X:
  532.                     undot();
  533.                     fex = MINFIELDX - fex;
  534.                     dot();
  535.                 break;
  536.                 case KEY_Y:
  537.                     undot();
  538.                     fey = MINFIELDY - fey;
  539.                     dot();
  540.                 break;
  541.                 case NUMERICFOUR:
  542.                 case LEFT:
  543.                     undot();
  544.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  545.                     {   fex = 0;
  546.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  547.                     {   fex = fexwrap(fex - ALTJUMP);
  548.                     } else
  549.                     {   fex = fexwrap(fex - 1);
  550.                     }
  551.                     if (sticky)
  552.                     {   stamp(brush);
  553.                     } else
  554.                     {   dot();
  555.                     }
  556.                 break;
  557.                 case NUMERICSIX:
  558.                 case RIGHT:
  559.                     undot();
  560.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  561.                     {   fex = MINFIELDX;
  562.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  563.                     {   fex = fexwrap(fex + ALTJUMP);
  564.                     } else
  565.                     {   fex = fexwrap(fex + 1);
  566.                     }
  567.                     if (sticky)
  568.                     {   stamp(brush);
  569.                     } else
  570.                     {   dot();
  571.                     }
  572.                 break;
  573.                 case NUMERICEIGHT:
  574.                 case UP:
  575.                     undot();
  576.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  577.                     {   fey = 0;
  578.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  579.                     {   fey = feywrap(fey - ALTJUMP);
  580.                     } else
  581.                     {   fey = feywrap(fey - 1);
  582.                     }
  583.                     if (sticky)
  584.                     {   stamp(brush);
  585.                     } else
  586.                     {   dot();
  587.                     }
  588.                 break;
  589.                 case NUMERICFIVE:
  590.                 case NUMERICTWO:
  591.                 case DOWN:
  592.                     undot();
  593.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  594.                     {   fey = MINFIELDY;
  595.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  596.                     {   fey = feywrap(fey + ALTJUMP);
  597.                     } else
  598.                     {   fey = feywrap(fey + 1);
  599.                     }
  600.                     if (sticky)
  601.                     {   stamp(brush);
  602.                     } else
  603.                     {   dot();
  604.                     }
  605.                 break;
  606.                 case NUMERICSEVEN:
  607.                     undot();
  608.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  609.                     {   fex = 0;
  610.                         fey = 0;
  611.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  612.                     {   fex = fexwrap(fex - ALTJUMP);
  613.                         fey = feywrap(fey - ALTJUMP);
  614.                     } else
  615.                     {   fex = fexwrap(fex - 1);
  616.                         fey = feywrap(fey - 1);
  617.                     }
  618.                     if (sticky)
  619.                     {   stamp(brush);
  620.                     } else
  621.                     {   dot();
  622.                     }
  623.                 break;
  624.                 case NUMERICNINE:
  625.                     undot();
  626.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  627.                     {   fex = MINFIELDX;
  628.                         fey = 0;
  629.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  630.                     {   fex = fexwrap(fex + ALTJUMP);
  631.                         fey = feywrap(fey - ALTJUMP);
  632.                     } else
  633.                     {   fex = fexwrap(fex + 1);
  634.                         fey = feywrap(fey - 1);
  635.                     }
  636.                     if (sticky)
  637.                     {   stamp(brush);
  638.                     } else
  639.                     {   dot();
  640.                     }
  641.                 break;
  642.                 case NUMERICONE:
  643.                     undot();
  644.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  645.                     {   fex = 0;
  646.                         fey = MINFIELDY;
  647.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  648.                     {   fex = fexwrap(fex - ALTJUMP);
  649.                         fey = feywrap(fey + ALTJUMP);
  650.                     } else
  651.                     {   fex = fexwrap(fex - 1);
  652.                         fey = feywrap(fey + 1);
  653.                     }
  654.                     if (sticky)
  655.                     {   stamp(brush);
  656.                     } else
  657.                     {   dot();
  658.                     }
  659.                 break;
  660.                 case NUMERICTHREE:
  661.                     undot();
  662.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  663.                     {   fex = MINFIELDX;
  664.                         fey = MINFIELDY;
  665.                     } elif ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  666.                     {   fex = fexwrap(fex + ALTJUMP);
  667.                         fey = feywrap(fey + ALTJUMP);
  668.                     } else
  669.                     {   fex = fexwrap(fex + 1);
  670.                         fey = feywrap(fey + 1);
  671.                     }
  672.                     if (sticky)
  673.                     {   stamp(brush);
  674.                     } else
  675.                     {   dot();
  676.                     }
  677.                 break;
  678.                 default:
  679.                 break;
  680.                 } // hctiws
  681.             break;
  682.             case IDCMP_MOUSEBUTTONS:
  683.                 if (code == SELECTDOWN)
  684.                 {   pointerx = oldxpixeltosquare(mousex);
  685.                     pointery = oldypixeltosquare(mousey);
  686.                     leftdown = TRUE;
  687.                     if (pointerx == GADGETX)
  688.                     {   if (pointery == GOLDGADGET)
  689.                             setbrush(GOLD);
  690.                         elif (pointery == SILVERGADGET)
  691.                             setbrush(SILVER);
  692.                         elif (pointery == EMPTYGADGET)
  693.                             setbrush(EMPTY);
  694.                         elif (pointery == WOODGADGET)
  695.                             setbrush(WOOD);
  696.                         elif (pointery == DYNAMITEGADGET)
  697.                             setbrush(DYNAMITE);
  698.                         elif (pointery == STONEGADGET)
  699.                             setbrush(STONE);
  700.                         elif (pointery == METALGADGET)
  701.                             setbrush(METAL);
  702.                         elif (pointery == FROSTGADGET)
  703.                             setbrush(FROST);
  704.                     } else
  705.                     {   pointerx = xpixeltosquare(mousex);
  706.                         pointery = ypixeltosquare(mousey);
  707.                         if (valid(pointerx, pointery))
  708.                         {   undot();
  709.                             fex = pointerx;
  710.                             fey = pointery;
  711.                             stamp(brush);
  712.                 }   }   }
  713.                 elif (code == SELECTUP)
  714.                 {   leftdown = FALSE;
  715.                 } elif (code == MENUUP)
  716.                 {   pointerx = xpixeltosquare(mousex);
  717.                     pointery = ypixeltosquare(mousey);
  718.                     if (valid(pointerx, pointery))
  719.                     {   undot();
  720.                         fex = pointerx;
  721.                         fey = pointery;
  722.                         stamp(EMPTY);
  723.                 }   }
  724.             break;
  725.             case IDCMP_CLOSEWINDOW:
  726.                 cleanexit(EXIT_SUCCESS);
  727.             break;
  728.             case IDCMP_REFRESHWINDOW:
  729.                 GT_BeginRefresh(MainWindowPtr);
  730.                 GT_EndRefresh(MainWindowPtr, TRUE);
  731.             break;
  732.             default:
  733.                 /* IDCMP_MENUVERIFY, IDCMP_INTUITICKS, IDCMP_ACTIVEWINDOW */
  734.             break;
  735.     }   }   }
  736.  
  737.     /* exit to title screen */
  738.  
  739.     if (!(ModifyIDCMP(MainWindowPtr, IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS | IDCMP_CLOSEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MENUPICK | IDCMP_MENUVERIFY | CYCLEIDCMP | STRINGIDCMP | CHECKBOXIDCMP | IDCMP_REFRESHWINDOW | IDCMP_INTUITICKS)))
  740.     {   DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: ModifyIDCMP() failed!\0", 24);
  741.     cleanexit(EXIT_FAILURE);
  742.     }
  743.     OffMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, NOITEM, NOSUB));
  744.     if (timer)
  745.     {   AbortIO((struct IORequest *) TimerRqPtr);
  746.          WaitIO((struct IORequest *) TimerRqPtr);
  747.     }
  748.     setpointer(NORMAL);
  749.     if (clearthem)
  750.         clearhiscores();
  751. }
  752.  
  753. MODULE void stamp(UBYTE square)
  754. {   if (square == START)
  755.     {   fedraw(startx[level], starty[level], EMPTY);
  756.         board[level][startx[level]][starty[level]] = EMPTY;
  757.         startx[level] = fex;
  758.         starty[level] = fey;
  759.         board[level][fex][fey] = EMPTY;
  760.     } else
  761.     {   board[level][fex][fey] = square;
  762.     }
  763.  
  764.     fedraw(fex, fey, square);
  765.     dot();
  766.     modified = clearthem = TRUE;
  767. }
  768.  
  769. MODULE void undot(void)
  770. {   if (startx[level] == fex && starty[level] == fey)
  771.         fedraw(fex, fey, START);
  772.     else fedraw(fex, fey, board[level][fex][fey]);
  773. }
  774.  
  775. MODULE void fillfield(UBYTE which)
  776. {   SBYTE x, y;
  777.  
  778.     // Service routine for level editor.
  779.  
  780.     for (x = 0; x <= MINFIELDX; x++)
  781.     {   for (y = 0; y <= MINFIELDY; y++)
  782.         {   board[level][x][y] = which;
  783.             fedraw(x, y, which);
  784.     }   }
  785.     board[level][startx[level]][starty[level]] = EMPTY;
  786.     fedraw(startx[level], starty[level], START);
  787.     dot();
  788. }
  789.  
  790. AGLOBAL void setbrush(UBYTE newbrush)
  791. {   brush = newbrush;
  792.     setpointer(brush);
  793.     underline(brush);
  794. }
  795.  
  796. MODULE void underline(UBYTE square)
  797. {   /* Removes old underline, draws new underline.
  798.  
  799.     square: which square-type to underline, or 255 for clear only.
  800.     Squares which do not correspond to any pseudo-gadgets
  801.     (eg. objects) are converted to 255s. */
  802.  
  803.     PERSIST SWORD oldy = 255;
  804.     AUTO    SWORD y;
  805.  
  806.     switch(square)
  807.     {
  808.     case EMPTY:
  809.         y = STARTYPIXEL + (EMPTYGADGET * SQUAREY);
  810.     break;
  811.     case SILVER:
  812.         y = STARTYPIXEL + (SILVERGADGET * SQUAREY);
  813.     break;
  814.     case GOLD:
  815.         y = STARTYPIXEL + (GOLDGADGET * SQUAREY);
  816.     break;
  817.     case DYNAMITE:
  818.         y = STARTYPIXEL + (DYNAMITEGADGET * SQUAREY);
  819.     break;
  820.     case WOOD:
  821.         y = STARTYPIXEL + (WOODGADGET * SQUAREY);
  822.     break;
  823.     case STONE:
  824.         y = STARTYPIXEL + (STONEGADGET * SQUAREY);
  825.     break;
  826.     case METAL:
  827.         y = STARTYPIXEL + (METALGADGET * SQUAREY);
  828.     break;
  829.     default:
  830.         square = 255;
  831.         y = 0; // to avoid spurious warnings
  832.     break;
  833.     }
  834.  
  835.     if (oldy != 255)
  836.     {   SetAPen(MainWindowPtr->RPort, BLACK);
  837.         Move(MainWindowPtr->RPort, STARTXPIXEL - 4, oldy);
  838.         Draw(MainWindowPtr->RPort, STARTXPIXEL - 4, oldy + SQUAREY);
  839.     }
  840.     if (square != 255)
  841.     {   SetAPen(MainWindowPtr->RPort, WHITE);
  842.         Move(MainWindowPtr->RPort, STARTXPIXEL - 4, y);
  843.         Draw(MainWindowPtr->RPort, STARTXPIXEL - 4, y + SQUAREY);
  844.         oldy = y;
  845. }   }
  846.  
  847. AGLOBAL void dot(void)
  848. {   SWORD x, xx, y, yy;
  849.  
  850.     /* Squares are dotted as follows:
  851.     
  852.          012345678901
  853.         0............
  854.         1............
  855.         2............
  856.         3............
  857.         4....WWW.....
  858.         5....WWWB....
  859.         6....WWWB....
  860.         7.....BBB....
  861.         8............
  862.         9............
  863.        10............
  864.        11............ */
  865.  
  866.         xx = ((fex + LEFTGAP) * SQUAREX) + STARTXPIXEL;
  867.         yy = ((fey +  TOPGAP) * SQUAREY) + STARTYPIXEL;
  868.  
  869.     if (sticky)
  870.         SetAPen(MainWindowPtr->RPort, RED);
  871.     else SetAPen(MainWindowPtr->RPort, WHITE);
  872.         for (x = 4; x <= 6; x++)
  873.         {   for (y = 4; y <= 6; y++)
  874.             {   WritePixel(MainWindowPtr->RPort, xx + x, yy + y);
  875.         }   }
  876.         SetAPen(MainWindowPtr->RPort, BLACK);
  877.         WritePixel(MainWindowPtr->RPort, xx + 7, yy + 5);
  878.         WritePixel(MainWindowPtr->RPort, xx + 7, yy + 6);
  879.         WritePixel(MainWindowPtr->RPort, xx + 5, yy + 7);
  880.         WritePixel(MainWindowPtr->RPort, xx + 6, yy + 7);
  881.         WritePixel(MainWindowPtr->RPort, xx + 7, yy + 7);
  882. }
  883.  
  884. MODULE void setpointer(UBYTE pointer)
  885. {   switch (pointer)
  886.     {
  887.     case EMPTY:
  888.         SetRGB4(&ScreenPtr->ViewPort, 17,  2,  2,  2);          /* fill */
  889.         SetRGB4(&ScreenPtr->ViewPort, 18,  2,  2,  2);          /* shadow */
  890.         SetRGB4(&ScreenPtr->ViewPort, 19,  2,  2,  2);          /* shine */
  891.         SetPointer(MainWindowPtr, CustomPointer, 6, 6, -3, -3);
  892.     break;
  893.     case DYNAMITE:
  894.         SetRGB4(&ScreenPtr->ViewPort, 17, 15,  8, 15);          /* fill */
  895.         SetRGB4(&ScreenPtr->ViewPort, 18, 15,  8, 15);          /* shadow */
  896.         SetRGB4(&ScreenPtr->ViewPort, 19, 15,  8, 15);          /* shine */
  897.         SetPointer(MainWindowPtr, CustomPointer, 6, 6, -3, -3);
  898.     break;
  899.     case WOOD:
  900.     SetRGB4(&ScreenPtr->ViewPort, 17,  8,  4,  2);        /* fill */
  901.         SetRGB4(&ScreenPtr->ViewPort, 18,  8,  4,  2);          /* shadow */
  902.         SetRGB4(&ScreenPtr->ViewPort, 19,  8,  4,  2);          /* shine */
  903.         SetPointer(MainWindowPtr, CustomPointer, 6, 6, -3, -3);
  904.     break;
  905.     case STONE:
  906.     SetRGB4(&ScreenPtr->ViewPort, 17,  0,  0,  0);        /* fill */
  907.         SetRGB4(&ScreenPtr->ViewPort, 18,  0,  0,  0);          /* shadow */
  908.         SetRGB4(&ScreenPtr->ViewPort, 19,  0,  0,  0);          /* shine */
  909.         SetPointer(MainWindowPtr, CustomPointer, 6, 6, -3, -3);
  910.     break;
  911.     case METAL:
  912.         SetRGB4(&ScreenPtr->ViewPort, 17, 10, 10, 10);          /* fill */
  913.         SetRGB4(&ScreenPtr->ViewPort, 18, 10, 10, 10);          /* shadow */
  914.         SetRGB4(&ScreenPtr->ViewPort, 19, 10, 10, 10);          /* shine */
  915.         SetPointer(MainWindowPtr, CustomPointer, 6, 6, -3, -3);
  916.     break;
  917.     case FROST:
  918.         SetRGB4(&ScreenPtr->ViewPort, 17, 12, 12, 15);          /* fill */
  919.         SetRGB4(&ScreenPtr->ViewPort, 18, 12, 12, 15);          /* shadow */
  920.         SetRGB4(&ScreenPtr->ViewPort, 19, 12, 12, 15);          /* shine */
  921.         SetPointer(MainWindowPtr, CustomPointer, 6, 6, -3, -3);
  922.     break;
  923.     default:
  924.         SetRGB4(&ScreenPtr->ViewPort, 17, 14,  4,  4); /* fill */
  925.         SetRGB4(&ScreenPtr->ViewPort, 18,  3,  3,  3); /* shadow */
  926.         SetRGB4(&ScreenPtr->ViewPort, 19, 12, 12, 12); /* shine */
  927.     ClearPointer(MainWindowPtr);
  928.     break;
  929. }   }
  930.  
  931. MODULE SBYTE oldxpixeltosquare(SWORD x)
  932. {   x = (x - STARTXPIXEL) / SQUAREX;
  933.     if (x < 0)
  934.         x--;
  935.     return ((SBYTE) x);
  936. }
  937. MODULE SBYTE oldypixeltosquare(SWORD y)
  938. {   y = (y - STARTYPIXEL) / SQUAREY;
  939.     if (y < 0)
  940.         y--;
  941.     return ((SBYTE) y);
  942. }
  943. MODULE SBYTE xpixeltosquare(SWORD x)
  944. {   x = ((x - STARTXPIXEL) / SQUAREX) - LEFTGAP;
  945.     if (x < 0)
  946.         x--;
  947.     return ((SBYTE) x);
  948. }
  949. MODULE SBYTE ypixeltosquare(SWORD y)
  950. {   y = ((y - STARTYPIXEL) / SQUAREY) - TOPGAP;
  951.     if (y < 0)
  952.         y--;
  953.     return ((SBYTE) y);
  954. }
  955.  
  956. MODULE void levelappend(void)
  957. {   UBYTE oldlevel;
  958.  
  959.     if (levels < MAXLEVELS)
  960.     {   oldlevel = level;
  961.         level = ++levels;
  962.         newfield();
  963.         level = oldlevel;
  964.         saylevel(WHITE);
  965. }   }
  966. MODULE void leveldelete(void)
  967. {   SBYTE i;
  968.  
  969.     /* pull boards */
  970.  
  971.     if (levels > 1)
  972.     {   if (level < levels)
  973.         for (i = level; i < levels; i++)
  974.             copyfield(i + 1, i);
  975.         else
  976.             level--;
  977.         levels--;
  978.         saylevel(WHITE);
  979.         turborender();
  980. }   }
  981. MODULE void levelerase(void)
  982. {   newfield();
  983.     turborender();
  984. }
  985. MODULE void levelinsert(void)
  986. {   UBYTE i;
  987.  
  988.     /* push boards */
  989.  
  990.     if (levels < MAXLEVELS)
  991.     {   for (i = levels; i >= level; i--)
  992.             copyfield(i, i + 1);
  993.         levels++;
  994.         saylevel(WHITE);
  995.         newfield();
  996.         turborender();
  997. }   }
  998. MODULE void copyfield(UBYTE source, UBYTE destination)
  999. {   SBYTE x, y;
  1000.  
  1001.     for (x = 0; x <= MINFIELDX; x++)
  1002.         for (y = 0; y <= MINFIELDY; y++)
  1003.             board[destination][x][y] = board[source][x][y];
  1004.     startx[destination] = startx[source];
  1005.     starty[destination] = starty[source];
  1006. }
  1007. MODULE SBYTE fexwrap(SBYTE x)
  1008. {   if (x < 0)
  1009.         x += MINFIELDX + 1;
  1010.     elif (x > MINFIELDX)
  1011.         x -= MINFIELDX + 1;
  1012.     return(x);
  1013. }
  1014. MODULE SBYTE feywrap(SBYTE y)
  1015. {   if (y < 0)
  1016.         y += MINFIELDY + 1;
  1017.     elif (y > MINFIELDY)
  1018.         y -= MINFIELDY + 1;
  1019.     return(y);
  1020. }
  1021.